#ifndef _TRANSITHUB_H_
#define _TRANSITHUB_H_


#include <pthread.h>
#include <string>
#include "logger.h"
// Revised for GS, 2013-03-29
#include <memory>
// Revision ends.

using namespace std;

#define LINUX
#define FAILURE 0
#define SUCCUSS 1

//#define NONE (2)
//#define REPLY (3)


#define MOTORNUM 20


//data packets enum
enum packet_types
{
    PACKET_NULL,		//0
    PACKET_MOTION,		//1
    PACKET_PING,		//2
    PACKET_CHECK,		//3
    PACKET_SET_INIT,	//4
    PACKET_GYRO_PRESS,	//5
    PACKET_LOCK,		//6
};
struct msg_state
{
    bool TX=1;
    bool GYP=0;
};
class transitHub
{
private:
    bool bOpen;
    long m_gaitCycle;
    double m_gyroscope_correct;
    pthread_mutex_t m_lock;
#ifdef LINUX
    int fd;
#else
    HANDLE hCom;	//for serial
#endif
    int simulator_motins[20];
    int initmotor[20];

    string m_imu_version; //0: AM, 1: BM
    string m_robot_version;

    bool ros_simular;
public:
    msg_state state;
    int store_data[20];
    double p_acc[3],p_gyp[3];
    bool p_loop;
    transitHub();
    ~transitHub();
    bool recordGait;
    string p_gaitName;
//    GaitStep* m_gait;
    bool portOpen(int comNumber, int baudRate);
    //"COM1","COM2" or "/dev/ttyS0"
    bool isOpen();
    bool portClose();
    void create_thread();
    int transmit(int *data,packet_types type = PACKET_MOTION);
    //the return value refers to the actual number of the transmitted data
    //PACKET_MOTION data = {20 values, i.e. 20 motors's goal position}
    //PACKET_PING: data = {null}
    //PACKET_CHECK data = {2 values, i.e. 1st refers to the motor id, 2nd refers to the control word}
    //PACKET_SET_INIT data = {2 values, i.e. 1st refers to the motor id, 2nd refers to the goal position}
    //PACKET_GYRO_PRESS: data = {2 value, i.e. 1st refers to gyro if it's 0, to press if it's 1, 2nd refers to return command if it's 1, to NOT return command if it's 0}
    //PACKET_LOCK: data = {2 values, i.e. 1st refers to the motor id, 2nd refers to lock if it's 1, to unlock if it's 0}
    int receive(char *str,int length);
    //the return value refers to the actual number of the received data
    int makeStdData(char *str,int *data,packet_types type);
    //generate the result string(str) from the input(data), according to the packet type(type),return the length of the string

    void gypdatatransform(char *temp);
    void feetdatatransform(char *temp);

    //basic task of receiving processes
    void doRx(char *recv = NULL,int failureCount = 0);

    //basic task of transmitting processes
    void Tx(int* body=NULL);
    void doLoopTx(int *body = NULL, int *camera = NULL);
    void LoopRx();
    void doWriteCommandTx(int idOrItem, int para, packet_types type);
    void doCheckTx(int id = 0,bool pos = false, bool temp = false, bool vol = false, bool load = false);

    long getGaitTime();
    void clearGaitTime();
    void increaseGaitTime();

    // Revised for GS, 2013-03-29
public:
    friend class std::auto_ptr<transitHub>;
    static transitHub* getInstance() throw(std::bad_alloc);
    // Revision ends.
};


#endif
